<?php

namespace app\api\controller\Leave;

use app\api\controller\Common;
use app\api\Logic\Campusclass\CampusClassCourseSignLogic;
use app\api\Logic\Campusclass\CampusClassLeaveLogic;
use app\api\model\CampusClassLeaveModel;
use think\Db;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\exception\DbException;

/**
 * 请假接口
 */
class Leave extends Common
{
    protected $noNeedLogin = ['*'];

    protected $campusClassCourseSignLogic;
    protected $campusClassLeaveLogic;

    public function _initialize()
    {
        parent::_initialize();
        $this->campusClassCourseSignLogic = new CampusClassCourseSignLogic();
        $this->campusClassLeaveLogic = new CampusClassLeaveLogic();
    }

    /**
     * 请假类型映射
     * @return array[]
     */
    protected function leaveTypeMap(){
        return [
            1 => ['type' => 1, 'name' => '事假'],
            2 => ['type' => 2, 'name' => '病假'],
            3 => ['type' => 3, 'name' => '其他'],
        ];
    }

    /**
     * 供前端调用，返回请假类型
     */
    public function leaveTypeAry(){
        $list = array_values($this->leaveTypeMap());
        if (!empty($list)) {
            $this->success('查询成功', $list);
        }
        $this->error('暂无数据');
    }

    /**
     * 根据请假时间返回涉及课次
     * @return void
     */
    public function courseByLeave(){
        if($this->request->isPost()){
            $param = $this->request->param();
            //验证数据
            $param = $this->verifyData($param);

            $startTime = isset($param['start_time']) && !empty($param['start_time']) ? strtotime($param['start_time']) : 0;
            $endTime = isset($param['end_time']) && !empty($param['end_time']) ? strtotime($param['end_time']) : 0;
            if(empty($startTime) || empty($endTime)){
                $this->error('时间不能为空');
            }

            //获取日期段内涉及的课次
            $involveCourse = $this->campusClassCourseSignLogic->getInvolve($param['user_id'],$startTime,$endTime,[0,1]);
            if(!empty($involveCourse)){
                $this->success('查询成功',$involveCourse);
            }
            $this->error('暂无数据');
        }
        $this->error('请求错误');
    }

    /**
     * 按时间请假
     * @throws Exception
     */
    public function leaveByDate(){
        if($this->request->isPost()){
            $param = $this->request->param();
            //验证数据
            $param = $this->verifyData($param);

            //请假类型
            $leaveType = $param['leave_type'] ?? 1;
            $startTime = isset($param['start_time']) && !empty($param['start_time']) ? strtotime($param['start_time']) : 0;
            $endTime = isset($param['end_time']) && !empty($param['end_time']) ? strtotime($param['end_time']) : 0;
            if(empty($startTime) || empty($endTime)){
                $this->error('请假时间不能为空');
            }

            if(empty($param['content'])){
                $this->error('请假理由不能为空');
            }

            //验证学员是否允许请假
            $isCan = $this->campusClassLeaveLogic->isCan($param['shop_id'],$param['user_id']);
            if(!$isCan){
                $this->error('该学员不允许请假');
            }

            //验证学员是否重复请假
            $isRepeat = $this->campusClassLeaveLogic->isRepeat($param['shop_id'],$param['user_id'],$startTime,$endTime);
            if($isRepeat){
                $this->error('此学员在该时间段已请假');
            }

            //获取日期段内涉及的课次
            $involveCourse = $this->campusClassCourseSignLogic->getInvolve($param['user_id'],$startTime,$endTime,[0,1]);
            $signIds = !empty($involveCourse) ? array_column($involveCourse,'id') : [];

            Db::startTrans();
            try {
                //请假期间涉及的课程全部改为请假状态
                if(!empty($signIds)){
                    $this->campusClassCourseSignLogic->updateStatus($signIds,3);
                }

                //添加请假记录
                CampusClassLeaveModel::insert([
                    'shop_id' => $param['shop_id'],
                    'user_id' => $param['user_id'],
                    'leave_type' => 1,
                    'start_time' => $startTime,
                    'end_time' => $endTime,
                    'sign_ids' => !empty($signIds) ? implode(',',$signIds) : '',
                    'type' => $leaveType,
                    'content' => $param['content'],
                    'images' => $param['images'] ?? '',
                    'status' => 1,
                    'createtime' => time()
                ]);

                Db::commit();
                $this->success('请假成功');
            }catch (Exception $e){
                Db::rollback();
                throw $e;
            }
        }
        $this->error('请求错误');
    }

    /**
     * 按课次请假
     * @throws Exception
     */
    public function leaveByCourse(){
        if($this->request->isPost()){
            $param = $this->request->param();
            //验证数据
            $param = $this->verifyData($param);

            //请假类型
            $leaveType = $param['leave_type'] ?? 1;
            $signIds = $param['sign_ids'] ?? '';
            if(empty($signIds)){
                $this->error('请假课次不能为空');
            }

            if(empty($param['content'])){
                $this->error('请假理由不能为空');
            }

            //验证学员是否允许请假
            $isCan = $this->campusClassLeaveLogic->isCan($param['shop_id'],$param['user_id']);
            if(!$isCan){
                $this->error('该学员不允许请假');
            }

            $signIds = explode(',',$signIds);

            Db::startTrans();
            try {
                //请假期间涉及的课程全部改为请假状态
                if(!empty($signIds)){
                    $this->campusClassCourseSignLogic->updateStatus($signIds,3);
                }

                //添加请假记录
                CampusClassLeaveModel::insert([
                    'shop_id' => $param['shop_id'],
                    'user_id' => $param['user_id'],
                    'leave_type' => 1,
                    'start_time' => 0,
                    'end_time' => 0,
                    'sign_ids' => !empty($signIds) ? implode(',',$signIds) : '',
                    'type' => $leaveType,
                    'content' => $param['content'],
                    'images' => $param['images'] ?? '',
                    'status' => 1,
                    'createtime' => time()
                ]);

                Db::commit();
                $this->success('请假成功');
            }catch (Exception $e){
                Db::rollback();
                throw $e;
            }
        }
        $this->error('请求错误');
    }

    /**
     * 请假列表
     * @return void
     * @throws DbException
     */
    public function list(){
        if($this->request->isPost()){
            $param = $this->request->param();
            //验证数据
            $param = $this->verifyData($param);

            $list = CampusClassLeaveModel::where('user_id',$param['user_id'])
                ->where('shop_id',$param['shop_id'])
                ->field('id,user_id,leave_type,start_time,end_time,type,status,createtime')
                ->with([
                    'userInfo' => function ($query) {
                        $query->withField('id,truename,avatar');
                    }
                ])->paginate(PAGE_SIZE);
            $list = objToArray($list) ?? [];

            if(!empty($list)){
                $this->success('查询成功',$list);
            }
            $this->error('暂无数据');
        }
        $this->error('请求错误');
    }

    /**
     * 请假详情
     * @return void
     * @throws DbException
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     */
    public function info(){
        if($this->request->isPost()){
            $param = $this->request->param();
            //验证数据
            $param = $this->verifyData($param);

            $leaveId = $param['leave_id'] ?? 0;
            if(!$leaveId){
                $this->error('请假记录ID必须');
            }

            $info = CampusClassLeaveModel::where('user_id',$param['user_id'])
                ->where('shop_id',$param['shop_id'])
                ->where('id',$leaveId)
                ->with([
                    'userInfo' => function ($query) {
                        $query->withField('id,truename,avatar');
                    },
                    'shopInfo' => function ($query) {
                        $query->withField('id,name,logo');
                    }
                ])
                ->field('id,user_id,shop_id,leave_type,start_time,end_time,content,sign_ids,type,status,images')
                ->find();
            $info = objToArray($info) ?? [];

            if(!empty($info)){
                $signIds = !empty($info['sign_ids']) ? explode(',',$info['sign_ids']) : [];
                $info['sign_list'] = [];
                if(!empty($signIds)){
                    $info['sign_list'] = $this->campusClassCourseSignLogic->getListBySignIds($signIds);
                }
                $this->success('查询成功',$info);
            }
            $this->error('暂无数据');
        }
        $this->error('请求错误');
    }

    /**
     * 撤销请假申请
     * @return void
     */
    public function cancelLeave(){
        if($this->request->isPost()) {
            $param = $this->request->param();
            //验证数据
            $param = $this->verifyData($param);

            $leaveId = $param['leave_id'] ?? 0;
            if(empty($leaveId)){
                $this->error('请选择请假记录');
            }

            //获取请假记录详情
            $leaveInfo = $this->campusClassLeaveLogic->getInfo($leaveId);
            if(empty($leaveInfo)){
                $this->error('请假记录不存在');
            }

            if($leaveInfo['status'] != 1){
                $this->error('当前状态无法撤销');
            }

            Db::startTrans();
            try {
                $signIds = !empty($leaveInfo['signIds']) ? explode(',',$leaveInfo['signIds']) : [];
                foreach ($signIds as $signId){
                    $signInfo = $this->campusClassCourseSignLogic->getInfo($signId);
                    $this->campusClassCourseSignLogic->updateStatus($signId,$signInfo['old_status']);
                }

                //撤销请假申请
                CampusClassLeaveModel::where('id',$leaveId)
                    ->update(['status' => 4]);

                Db::commit();
                $this->success('撤销成功');
            }catch (Exception $e){
                Db::rollback();
                $this->error('撤销失败');
            }
        }
        $this->error('请求错误');
    }
}
